﻿// Decompiled with JetBrains decompiler
// Type: System.Web.Razor.Parser.SyntaxTree.Span
// Assembly: System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// MVID: 682513D6-F37E-48AC-9909-F3EE103CFF14
// Assembly location: D:\Project\Idea\无人机外网\uav\客户端工程\排查工具\bin\Release\System.Web.Razor.dll

using Microsoft.Internal.Web.Utils;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Razor.Editor;
using System.Web.Razor.Generator;
using System.Web.Razor.Text;
using System.Web.Razor.Tokenizer.Symbols;

namespace System.Web.Razor.Parser.SyntaxTree
{
  /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Represents a Razor parse tree node that contains the all the content of a block node.</summary>
  public class Span : SyntaxTreeNode
  {
    private SourceLocation _start;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Initializes a new instance of the <see cref="T:System.Web.Razor.Parser.SyntaxTree.Span" /> class.</summary>
    /// <param name="builder">The builder to use for this span.</param>
    public Span(SpanBuilder builder) => this.ReplaceWith(builder);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets the kind for this span.</summary>
    /// <returns>One of the values of the <see cref="T:System.Web.Razor.Parser.SyntaxTree.SpanKind" /> enumeration.</returns>
    public SpanKind Kind { get; protected set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets the symbols used to generate the code for the span.</summary>
    /// <returns>The symbols used to generate the code for the span.</returns>
    public IEnumerable<ISymbol> Symbols { get; protected set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets the previous span in the tree node.</summary>
    /// <returns>The previous span in the tree node.</returns>
    public Span Previous { get; protected internal set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets the next span in the tree node.</summary>
    /// <returns>The next span in the tree node.</returns>
    public Span Next { get; protected internal set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets the handler for span edits.</summary>
    /// <returns>The handler for span edits.</returns>
    public SpanEditHandler EditHandler { get; protected set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets the code generator for the span.</summary>
    /// <returns>The code generator for the span.</returns>
    public ISpanCodeGenerator CodeGenerator { get; protected set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets a value that indicates whether this node is a block node.</summary>
    /// <returns>false.</returns>
    public override bool IsBlock => false;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets the length of the span content.</summary>
    /// <returns>The length of the span content.</returns>
    public override int Length => this.Content.Length;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets the start character location of the span.</summary>
    /// <returns>The start character location of the span.</returns>
    public override SourceLocation Start => this._start;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets the content of the span.</summary>
    /// <returns>The content of the span.</returns>
    public string Content { get; private set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Changes the span builder for this span.</summary>
    /// <param name="changes">A delegate that will be executed along with this change.</param>
    public void Change(Action<SpanBuilder> changes)
    {
      SpanBuilder builder = new SpanBuilder(this);
      changes(builder);
      this.ReplaceWith(builder);
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Replaces the span builder for this span with the specified span builder.</summary>
    /// <param name="builder">The new builder to use for this span.</param>
    public void ReplaceWith(SpanBuilder builder)
    {
      this.Kind = builder.Kind;
      this.Symbols = (IEnumerable<ISymbol>) builder.Symbols;
      this.EditHandler = builder.EditHandler;
      this.CodeGenerator = builder.CodeGenerator ?? SpanCodeGenerator.Null;
      this._start = builder.Start;
      builder.Reset();
      this.Content = this.Symbols.Aggregate<ISymbol, StringBuilder, string>(new StringBuilder(), (Func<StringBuilder, ISymbol, StringBuilder>) ((sb, sym) => sb.Append(sym.Content)), (Func<StringBuilder, string>) (sb => sb.ToString()));
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Accepts visit from the specified visitor.</summary>
    /// <param name="visitor">The object that performs the visit.</param>
    public override void Accept(ParserVisitor visitor) => visitor.VisitSpan(this);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Returns the string representation of this current span.</summary>
    /// <returns>The string representation of this current span.</returns>
    public override string ToString()
    {
      StringBuilder stringBuilder = new StringBuilder();
      stringBuilder.Append((object) this.Kind);
      stringBuilder.AppendFormat(" Span at {0}::{1} - [{2}]", (object) this.Start, (object) this.Length, (object) this.Content);
      stringBuilder.Append(" Edit: <");
      stringBuilder.Append(this.EditHandler.ToString());
      stringBuilder.Append(">");
      stringBuilder.Append(" Gen: <");
      stringBuilder.Append(this.CodeGenerator.ToString());
      stringBuilder.Append("> {");
      stringBuilder.Append(string.Join(";", this.Symbols.GroupBy<ISymbol, Type>((Func<ISymbol, Type>) (sym => sym.GetType())).Select<IGrouping<Type, ISymbol>, string>((Func<IGrouping<Type, ISymbol>, string>) (grp => grp.Key.Name + ":" + (object) grp.Count<ISymbol>()))));
      stringBuilder.Append("}");
      return stringBuilder.ToString();
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Sets the start character location of this span.</summary>
    /// <param name="newStart">The new start location to set for this span.</param>
    public void ChangeStart(SourceLocation newStart)
    {
      this._start = newStart;
      Span span = this;
      SourceLocationTracker sourceLocationTracker = new SourceLocationTracker(newStart);
      sourceLocationTracker.UpdateLocation(this.Content);
      while ((span = span.Next) != null)
      {
        span._start = sourceLocationTracker.CurrentLocation;
        sourceLocationTracker.UpdateLocation(span.Content);
      }
    }

    internal void SetStart(SourceLocation newStart) => this._start = newStart;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Determines whether the specified node is equivalent to this span.</summary>
    /// <returns>true if the specified node is equal to this span; otherwise, false.</returns>
    /// <param name="node">The node to compare with this span.</param>
    public override bool EquivalentTo(SyntaxTreeNode node) => node is Span span && this.Kind.Equals((object) span.Kind) && (this.Start.Equals(span.Start) && this.EditHandler.Equals((object) span.EditHandler)) && string.Equals(span.Content, this.Content, StringComparison.Ordinal);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Determines whether the specified object is equal to this span.</summary>
    /// <returns>true if the specified object is equal to this span; otherwise, false.</returns>
    /// <param name="obj">The object to compare to this span.</param>
    public override bool Equals(object obj) => obj is Span span && (this.Kind.Equals((object) span.Kind) && this.EditHandler.Equals((object) span.EditHandler) && this.CodeGenerator.Equals((object) span.CodeGenerator)) && this.Symbols.SequenceEqual<ISymbol>(span.Symbols);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Returns the hash code for this current span.</summary>
    /// <returns>The hash code for this current span.</returns>
    public override int GetHashCode() => HashCodeCombiner.Start().Add((int) this.Kind).Add((object) this.Start).Add((IEnumerable) this.Content).CombinedHash;
  }
}
